package model;

import java.util.List;

import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

/**
 * Модель для отображения списка объетов в таблицу с использованием типа
 * объектов.
 * 
 * @author aemaeth
 * 
 * @param <V>
 *            тип объекта
 */
public class ListTableModel<V> extends AbstractTableModel {
	private static final long serialVersionUID = 1L;

	private final List<V> list;
	private final Mapper<V> mapper;

	/**
	 * Создать модель над списком и менеджером.
	 * 
	 * @param list
	 *            список объектов.
	 * @param mapper
	 *            менеджер колонок
	 */
	public ListTableModel(List<V> list, Mapper<V> mapper) {
		this.list = list;
		this.mapper = mapper;
	}

	@Override
	public int getRowCount() {
		return list.size();
	}

	@Override
	public int getColumnCount() {
		return mapper.getCount();
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		return mapper.getSingleMapper(columnIndex).getValue(list.get(rowIndex));
	}

	@Override
	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		mapper.getSingleMapper(columnIndex).setValue(list.get(rowIndex), aValue);
		fireTableCellUpdated(rowIndex, columnIndex);
	}

	@Override
	public String getColumnName(int column) {
		String name = mapper.getSingleMapper(column).columnName();
		if (name == null)
			name = "";
		return name;
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		Class<?> clazz = mapper.getSingleMapper(columnIndex).getColumnClass();
		if (clazz == null)
			clazz = Object.class;
		return clazz;
	}

	/**
	 * Получить хранимый, связный список объектов.
	 * 
	 * @return список
	 */
	protected List<V> getList() {
		return list;
	}

	/**
	 * Получить менеджера колонок.
	 * 
	 * @return менеджер колонок
	 */
	protected Mapper<V> getMapper() {
		return mapper;
	}
	
	/**
	 * Сделать таблицу для этой модели.
	 * 
	 * @return новая таблица
	 */
	public UpdateableTable<V> makeTable() {
		return new UpdateableTable<V>(this, mapper);
	}
	
	/**
	 * Получить объект по индексу для обработки.
	 * @param index
	 * @return
	 */
	public V get(int index) {
		return list.get(index);
	}
	
	public void remove(V obj) {
		list.remove(obj);
		fireTableDataChanged();
	}
	public void add(V obj) {
		list.add(obj);
		fireTableDataChanged();
	}
	/**
	 * Фабричный метод создания модели из параметров конструктора.
	 * 
	 * @param list
	 *            список объектов
	 * @param mapper
	 *            менеджер колонок
	 * @return модель
	 */
	public static <E> ListTableModel<E> from(List<E> list, Mapper<E> mapper) {
		return new ListTableModel<E>(list, mapper);
	}
	
	/**
	 * Фабричный метод создания таблицы с моделью на указанном списке и
	 * менеджере.
	 * 
	 * @param list
	 *            список объектов
	 * @param mapper
	 *            менеджер колонок
	 * @return
	 */
	public static <E> JTable toTable(List<E> list, Mapper<E> mapper) {
		return new ListTableModel<E>(list, mapper).makeTable();
	}
}